這次一樣來分享來自"克服 JS 的奇怪部分"的學習筆記,這次要來介紹的是控制函數的方法。
先前我們須知道函數就是一個特殊形態的物件
,他有可有可無的名稱屬性,還有可以被呼叫的程式屬性。
而所有函數都擁有call()、bind()、apply()這些方法。
首先,在person的部分,我們知道this會指向當前的層級的位址,也就是person這個物件,而在logName我們會指向全域物件,發現找不到getFullName這個方法,故會報錯。
var person = {
firstname: 'John',
lastname: 'Doe',
getFullName: function() {
var fullname = this.firstname + ' ' + this.lastname;
return fullname;
}
}
var logName = function(lang1, lang2) {
console.log('Logged: ' + this.getFullName());
}
logName();
那如果我們可以控制this指向誰不是很好嗎?
所以,我們以logName使用bind方法,去複製擁有getFullName函式的person物件,由於他會回傳一個新的函數,所以我們創建一個新的變數logPersonName存取新的函數,並且呼叫他
var person = {
firstname: 'John',
lastname: 'Doe',
getFullName: function() {
var fullname = this.firstname + ' ' + this.lastname;
return fullname;
}
}
var logName = function(lang1, lang2) {
console.log('Logged: ' + this.getFullName());
console.log('Arguments: ' + lang1 + ' ' + lang2);
console.log('-----------');
}
var logPersonName = logName.bind(person);
logPersonName('en');
Logged: John Doe
Arguments: en undefined
-----------
可以發現,使用call他會直接執行,並且是可以傳入參數的。
var person = {
firstname: 'John',
lastname: 'Doe',
getFullName: function() {
var fullname = this.firstname + ' ' + this.lastname;
return fullname;
}
}
var logName = function(lang1, lang2) {
console.log('Logged: ' + this.getFullName());
console.log('Arguments: ' + lang1 + ' ' + lang2);
console.log('-----------');
}
logName.call(person, 'en', 'es');
Logged: John Doe
Arguments: en es
-----------
很明顯跟call是非常相似,差別在於傳入的參數型態。
var person = {
firstname: 'John',
lastname: 'Doe',
getFullName: function() {
var fullname = this.firstname + ' ' + this.lastname;
return fullname;
}
}
var logName = function(lang1, lang2) {
console.log('Logged: ' + this.getFullName());
console.log('Arguments: ' + lang1 + ' ' + lang2);
console.log('-----------');
}
logName.apply(person, ['en', 'es']);
但我們在實際應用用的到apply嗎?
也就是我們可以使用其他物件方法,就好像我們本身有它的屬性一樣。
var person = {
firstname: 'John',
lastname: 'Doe',
getFullName: function() {
var fullname = this.firstname + ' ' + this.lastname;
return fullname;
}
}
var person2 = {
firstname: 'Jane',
lastname: 'Doe'
}
console.log(person.getFullName.apply(person2));
Jane Doe
我們所給予的參數,會設定為複製函數的永久參數
,multipleByTwo第一個參數設為2,那我們我的a永遠就等於2,如同在 multiply函數中return a * b 前面新增var a = 2,而當我們設置兩個參數,在呼叫時也傳入參數,那麼我們呼叫時,傳入的參數將會失效,一樣是取我們原本設置的兩個參數。
function multiply(a, b) {
return a*b;
}
var multipleByTwo = multiply.bind(this, 2);
console.log(multipleByTwo(4)); // 8
var multipleByThree = multiply.bind(this, 3, 2);
console.log(multipleByThree(4)); // 6